import { exceCommand, stopProcess } from '@/services/command';
import { registerLogger, unRegisterLogger } from '@/services/logger';
import { readText, writeText } from '@tauri-apps/api/clipboard';
import { TerminalTypeEnum } from '@/utils/enums';
import {
  PauseCircleOutlined,
  PlayCircleOutlined,
  SyncOutlined,
} from '@ant-design/icons';
import { useMemoizedFn, useRequest } from 'ahooks';
import React, { useEffect, useState } from 'react';
import { Tooltip } from 'antd';
import { Terminal } from 'xterm';
import XtermTerminal from '@rasir/xterm-terminal';
import { TerminalApi, XTerminal } from '@rasir/xterm-terminal/lib/types';
import { nextTick } from '@rasir/xterm-terminal/lib/XtermTerminal';
import './index.less';

const terminalTitleTemplate = '$: ';
const preLog = '\r\n*** COMMAND START ***\r\n';

interface TerminalProps {
  height?: number;
  logs?: string[]; // 日志
  code: string; // 项目编码
  terminalkey: string; // 终端唯一标识
  command?: string; // 执行命令
  workSpace?: string; // 工作空间
  type: TerminalType;
}

type NTerminal = Terminal & {
  _core: {
    buffer: {
      x: number;
    };
  };
};

const TerminalPage: React.FC<TerminalProps> = (props) => {
  const [xtermApi, setApi] = useState<TerminalApi>();
  const { type, workSpace, command, height, terminalkey, code } = props;
  const [codeWrapperheight, setCodeWrapperHeight] = useState<number>();
  const [pid, setPid] = useState<number | undefined>();
  const [running, setRunning] = useState<boolean>(false);

  const { runAsync: exceCommandRun, loading: exceCommandLoading } = useRequest(
    exceCommand,
    {
      manual: true,
    },
  );

  const commandRunning: boolean = exceCommandLoading || running;

  useEffect(() => {
    if (height) {
      setCodeWrapperHeight(height - 70);
    }
  }, [height]);
  // 获取日志
  const getLogs = useMemoizedFn((log: string) => {
    if (log) {
      xtermApi?.writeln(log);
      let isEnd = log && /^\[END\]/.test(log);
      if (isEnd) {
        xtermApi?.writeln('');
        setRunning(false);
        setPid(undefined);
      }
    }
  });

  // 运行设定的命令
  const runCommand = useMemoizedFn(async (cmdText?: string) => {
    // xtermApi?.writeln('');
    const cmd = (cmdText || command || '').trim();
    if (!cmd) return;
    const params: any = {
      terminalkey,
      workSpace,
      command: cmd || command,
      code,
    };
    const runRet: number = (await exceCommandRun(params).catch(() => {
      setRunning(false);
    })) as number;
    if (runRet) {
      setPid(runRet);
      setRunning(true);
    }
  });

  // 停止运行命令
  const stopCommand = useMemoizedFn(() => {
    stopProcess(terminalkey);
    setPid(undefined);
  });

  // 复制
  const onCopy = async (text: string) => await writeText(text);
  // 粘贴
  const onPaste = async () => (await readText()) || '';

  useEffect(() => {
    registerLogger(terminalkey as string, getLogs);
    return () => {
      stopCommand();
      unRegisterLogger(terminalkey as string);
    };
  }, []);

  const changeDefaultCommand = useMemoizedFn(() => {
    if (pid) {
      stopCommand();
    }
    xtermApi?.clearLog();
  });

  const loaded = (_: XTerminal, api: TerminalApi) => {
    setApi(api);
  };

  useEffect(() => {
    changeDefaultCommand();
  }, [command]);

  useEffect(() => {
    if (xtermApi) {
      nextTick(() => xtermApi.resize());
    }
  }, [codeWrapperheight]);

  return (
    <div className="terminal-page">
      <div className="terminal-btns">
        {type === TerminalTypeEnum.COMMAND && !commandRunning ? (
          <Tooltip title="开始执行">
            <PlayCircleOutlined onClick={() => runCommand()} />
          </Tooltip>
        ) : (
          <Tooltip title="停止执行">
            <PauseCircleOutlined onClick={stopCommand} />
          </Tooltip>
        )}
        <SyncOutlined
          spin={commandRunning}
          onClick={xtermApi?.clearLog}
          style={{ fontSize: 12, cursor: 'default' }}
        />
        <b style={{ fontSize: 12, cursor: 'default' }}>pid: {pid || '---'}</b>
      </div>
      <div
        onKeyPressCapture={(e) => {
          // 避免与全局中的复制冲突
          if (e.charCode === 99) {
            e.stopPropagation();
          }
        }}
        style={{
          overflow: 'hidden',
          margin: '0 10px 10px 10px',
          height: codeWrapperheight,
          background: '#000',
          padding: '5px 10px',
          borderRadius: 4,
        }}
      >
        <XtermTerminal
          lineTitle={terminalTitleTemplate}
          height={(codeWrapperheight || 0) - 10}
          disableStdin={type === TerminalTypeEnum.COMMAND}
          onCommand={runCommand}
          onCopy={onCopy}
          onPaste={onPaste}
          command={type === TerminalTypeEnum.COMMAND ? command : undefined}
          preLog={preLog}
          onLoad={loaded}
          className="worker-terminal"
          options={{
            theme: {
              foreground: '#fff',
              background: '#000',
              selectionForeground: '#ccc',
            },
          }}
        />
      </div>
    </div>
  );
};

export default React.memo(TerminalPage);
